home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / aztecnos.arc / TIMER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-19  |  3.9 KB  |  179 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "timer.h"
  4. #include "proc.h"
  5.  
  6. extern int Tick;
  7. static void t_alarm();
  8. int32 Clock;        /* Count of ticks since startup */
  9. struct timer *Timers;    /* Head of running timer chain */
  10.  
  11. int
  12. timerproc()
  13. {
  14.     register struct timer *t;
  15.     register struct timer *expired = NULLTIMER;
  16.     char i_state;
  17.  
  18.     for(;;){
  19.         i_state = dirps();    /* Tick is modified by an interrupt */
  20.         while(Tick == 0)
  21.             pwait(&Tick);
  22.         Tick--;
  23.         restore(i_state);
  24.  
  25.         Clock++;
  26.         systick();    /* Machine-dependent per-tick stuff */
  27.  
  28.         /* Decrement the first timer. If it expires,
  29.          * take it off the running list and put it
  30.          * on a singly linked list of expired timers
  31.          */
  32.         if(Timers != NULLTIMER)
  33.             Timers->count--;
  34.         else
  35.             continue;    /* Nothing else on this tick */
  36.  
  37.         while(Timers != NULLTIMER && Timers->count == 0){
  38.             if(Timers->next == Timers){
  39.                 printf("PANIC: Timer loop at %lx\n",
  40.                  (long)Timers);
  41.                 iostop();
  42.                 exit(1);
  43.             }
  44.             /* Save Timers since stop_timer will change it */
  45.             t = Timers;
  46.             stop_timer(t);
  47.             t->state = TIMER_EXPIRE;
  48.             /* Add to expired timer list */
  49.             t->next = expired;
  50.             expired = t;
  51.         }
  52.         /* Now go through the list of expired timers, removing each
  53.          * one and kicking the notify function, if there is one
  54.          */
  55.         while((t = expired) != NULLTIMER){
  56.             expired = t->next;
  57.             if(t->func){
  58.                 (*t->func)(t->arg);
  59.             }
  60.         }
  61.     }
  62. }
  63. /* Start a timer */
  64. void
  65. start_timer(t)
  66. struct timer *t;
  67. {
  68.     register struct timer *tnext,*tprev;
  69.     int32 tot;
  70.  
  71.     if(t == NULLTIMER)
  72.         return;
  73.     if(t->state == TIMER_RUN)
  74.         stop_timer(t);
  75.     if(t->start == 0)
  76.         return;        /* A start value of 0 disables the timer */
  77.  
  78.     t->state = TIMER_RUN;
  79.     /* Find right place on list for this guy */
  80.     tot = 0;
  81.     tprev = NULLTIMER;
  82.     for(tnext = Timers;tnext != NULLTIMER;tnext = tprev->next){
  83.         if(tnext->count + tot > t->start)
  84.             break;
  85.         tprev = tnext;
  86.         tot += tnext->count;
  87.     }
  88.     /* At this point, tprev points to the entry that should go right
  89.      * before us, and tnext points to the entry just after us. Either or
  90.      * both may be null.
  91.      */
  92.     t->count = t->start - tot;    /* Adjust for entries before us */
  93.     if((t->prev = tprev) == NULLTIMER)
  94.         Timers = t;        /* Put at beginning */
  95.     else
  96.         tprev->next = t;
  97.  
  98.     if((t->next = tnext) != NULLTIMER){
  99.         tnext->prev = t;
  100.         /* Adjust the following entry's count */
  101.         tnext->count -= t->count;
  102.     }
  103. }
  104. /* Stop a timer */
  105. void
  106. stop_timer(t)
  107. register struct timer *t;
  108. {
  109.     register struct timer *tp;
  110.  
  111.     if(t == NULLTIMER)
  112.         return;
  113.     if(t->state == TIMER_RUN){
  114.         /* Delete from active timer list */
  115.         if(t->next != NULLTIMER)
  116.             t->next->prev = t->prev;
  117.         if(t->prev != NULLTIMER)
  118.             t->prev->next = t->next;
  119.         else
  120.             Timers = t->next;
  121.         /* Adjust count for the next timer */
  122.         if((tp = t->next) != NULLTIMER)
  123.             tp->count += t->count;
  124.     }
  125.     t->state = TIMER_STOP;
  126. }
  127. /* Return count of ticks remaining on this timer */
  128. int32
  129. read_timer(t)
  130. struct timer *t;
  131. {
  132.     register struct timer *tp;
  133.     int32 tot;
  134.  
  135.     if(t->state != TIMER_RUN)
  136.         return 0;
  137.  
  138.     tot = 0;
  139.     for(tp = Timers;tp != NULLTIMER; tp = tp->next){
  140.         tot += tp->count;
  141.         if(tp == t)
  142.             break;
  143.     }
  144.     return tot;
  145. }
  146. /* Delay process for specified number of ticks */
  147. void
  148. pause(ticks)
  149. int32 ticks;
  150. {
  151.     if(Curproc == NULLPROC || ticks == 0)
  152.         return;
  153.     alarm(ticks);
  154.     /* The actual event doesn't matter, since we'll be alerted */
  155.     while(Curproc->alarm.state == TIMER_RUN && pwait(Curproc) == 1)
  156.         ;
  157.  
  158.     alarm(0L); /* Make sure it's stopped, in case we were killed */    
  159. }
  160. /* Send signal to current process after specified number of ticks */
  161. void
  162. alarm(ticks)
  163. int32 ticks;
  164. {
  165.     if(Curproc != NULLPROC){
  166.         Curproc->alarm.start = ticks;
  167.         Curproc->alarm.func = t_alarm;
  168.         Curproc->alarm.arg = (char *)Curproc;
  169.         start_timer(&Curproc->alarm);
  170.     }
  171. }
  172. static void
  173. t_alarm(x)
  174. void *x;
  175. {
  176.     alert((struct proc *)x,1);
  177. }
  178.     
  179.